/*
 moxl - Modular XML Library
 Copyright (c) 2007, Malcolm Sparks

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package moxl.dom.support;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;

import moxl.dom.MoxlAttribute;
import moxl.dom.MoxlAttributeMap;
import moxl.dom.DefaultXmlNamespace;
import moxl.dom.QualifiedName;
import moxl.dom.XmlNamespace;

public class MoxlAttributeGroup implements MoxlAttributeMap
{
	private MoxlLocalAttributeGroup defaultGroup;
	private Map<XmlNamespace, MoxlLocalAttributeGroup> groups;
	private List<MoxlAttribute> list;

	public boolean contains(QualifiedName name)
	{
		MoxlLocalAttributeGroup group = getAttributeGroup(name.getNamespace());
		if (group == null)
		{
			return false;
		}
		return group.contains(name.getLocalPart());
	}

	private MoxlLocalAttributeGroup getAttributeGroup(XmlNamespace namespace)
	{
		if (namespace.equals(DefaultXmlNamespace.getInstance()))
		{
			return defaultGroup;
		}
		else
		{
			if (groups == null)
			{
				return null;
			}
			return groups.get(namespace);
		}
	}

	public void add(MoxlAttribute attribute)
	{
		QualifiedName name = attribute.getQName();
		MoxlLocalAttributeGroup group = getAttributeGroup(name.getNamespace());
		if (group == null)
		{
			if (name.getNamespace().equals(DefaultXmlNamespace.getInstance()))
			{
				defaultGroup = new MoxlLocalAttributeGroup(name.getNamespace());
				group = defaultGroup;
			}
			else
			{
				group = new MoxlLocalAttributeGroup(name.getNamespace());
				if (groups == null)
				{
					groups = new HashMap<XmlNamespace, MoxlLocalAttributeGroup>();
				}
				groups.put(name.getNamespace(), group);
			}
		}
		group.add(attribute);
		if (list == null)
		{
			list = new ArrayList<MoxlAttribute>();
		}
		list.add(attribute);
	}

	public MoxlAttribute get(QualifiedName name)
	{
		MoxlLocalAttributeGroup group = getAttributeGroup(name.getNamespace());
		if (group == null)
		{
			return null;
		}
		return group.get(name.getLocalPart());
	}

	public void remove(MoxlAttribute attribute)
	{
		MoxlLocalAttributeGroup group = groups.get(attribute.getQName().getNamespace());
		if (group == null)
		{
			throw new IllegalArgumentException("Attribute given in parameter (" + attribute + ") does not belong to this element");

		}
		MoxlAttribute removedAttribute = group.remove(attribute);
		if (!attribute.equals(removedAttribute))
		{
			throw new IllegalArgumentException("Attribute given in parameter (" + attribute + ") does not belong to this element");
		}
		list.remove(attribute);
	}

	public Iterator<MoxlAttribute> iterator()
	{
		if (list == null)
		{
			List<MoxlAttribute> emptyList = Collections.emptyList();
			return emptyList.iterator();
		}
		return list.iterator();
	}

	public MoxlAttribute get(String name)
	{
		if (defaultGroup == null)
		{
			return null;
		}
		else
		{
			return defaultGroup.get(name);
		}
	}

	public boolean containsAttribute(QualifiedName name)
	{
		MoxlLocalAttributeGroup group = getAttributeGroup(name.getNamespace());
		return group.contains(name.getLocalPart());
	}

	public MoxlAttribute getAttribute(QualifiedName name)
	{
		MoxlLocalAttributeGroup group = getAttributeGroup(name.getNamespace());
		if (group == null) // If there is not a group for the namespace, then there can't be an attribute.
		{
			return null;
		}
		return group.get(name.getLocalPart());
	}

	public boolean isEmpty()
	{
		return list == null || list.isEmpty();
	}

	public void removeAttribute(MoxlAttribute attribute)
	{
		if (list == null)
		{
			throw new NoSuchElementException();
		}
		MoxlLocalAttributeGroup attributeGroup = getAttributeGroup(attribute.getQName().getNamespace());
		attributeGroup.remove(attribute);
		list.remove(attribute);
	}

	public int size()
	{
		if (list == null)
		{
			return 0;
		}
		else
		{
			return list.size();
		}
	}

}
